/*
 * Copyright 2018 TFI Systems

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */

package com.galfins.gnss_compare;

import android.location.GnssMeasurementsEvent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;

import java.util.ArrayList;
import java.util.Observer;

/**
 * Class encapsulating generic operations on created CalculationModules.
 */
public class CalculationModulesArrayList extends ArrayList<CalculationModule> {

    private final String TAG = "CalculationModulesArrayList";

    private GnssMeasurementsEvent.Callback gnssCallback;
    private LocationManager locationManagerReference = null;

    private HandlerThread handlerThread;
    private Handler handler;

    public static abstract class PoseUpdatedListener {
        public abstract void onPoseUpdated();
    }

    private PoseUpdatedListener mPoseUpdatedListener = null;

    public void assignPoseUpdatedListener(PoseUpdatedListener newCallback) {
        mPoseUpdatedListener = newCallback;
    }

    public CalculationModulesArrayList() {
        handlerThread = new HandlerThread("");
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper());

        gnssCallback = new GnssMeasurementsEvent.Callback() {
            @Override
            public void onGnssMeasurementsReceived(final GnssMeasurementsEvent eventArgs) {
                super.onGnssMeasurementsReceived(eventArgs);

                final Runnable r =
                        new Runnable() {
                            @Override
                            public void run() {
                                for (CalculationModule calculationModule : CalculationModulesArrayList.this)
                                    calculationModule.updateMeasurements(eventArgs);

                                if (mPoseUpdatedListener != null)
                                    mPoseUpdatedListener.onPoseUpdated();
                            }
                        };
                handler.post(r);

//                for (CalculationModule calculationModule : CalculationModulesArrayList.this)
//                    calculationModule.updateMeasurements(eventArgs);
//
//                if (mPoseUpdatedListener != null)
//                    mPoseUpdatedListener.onPoseUpdated();
            }
        };
    }

    public void registerForGnssUpdates(LocationManager locationManager) {
        try {
            final LocationListener mLocationListener =
                    new LocationListener() {
                        @Override
                        public void onProviderEnabled(String provider) {
                        }

                        @Override
                        public void onProviderDisabled(String provider) {
                        }

                        @Override
                        public void onLocationChanged(Location location) {
                        }

                        @Override
                        public void onStatusChanged(String provider, int status, Bundle extras) {
                        }

                    };

            boolean isGpsProviderEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            if (isGpsProviderEnabled) {
                locationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER,
                        0,
                        0.0f /* minDistance */,
                        mLocationListener);
                locationManager.requestLocationUpdates(
                        LocationManager.GPS_PROVIDER,
                        0,
                        0.0f /* minDistance */,
                        mLocationListener);
            }
            locationManagerReference = locationManager;
            locationManager.registerGnssMeasurementsCallback(gnssCallback);

        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    public void unregisterFromGnssUpdates() {
        if (locationManagerReference != null)
            locationManagerReference.unregisterGnssMeasurementsCallback(gnssCallback);
    }
}
